﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using MahApps.Metro.Controls;
using System.IO;
using System.Xml;
using ICSharpCode.AvalonEdit.Highlighting;
using System.Windows.Controls.Primitives;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// PythonEditor.xaml 的交互逻辑
    /// </summary>
    public partial class PythonEditor : MetroWindow
    {
        /// <summary>
        /// 自定义高亮定义，完整定义。
        /// 但一千多行的帮助文档就明显延迟。
        /// </summary>
        private static IHighlightingDefinition pythonHighlighting;

        private static Converter.ModifiedToText modifiedToTextConverter = new LunarMarkdownEditor.Converter.ModifiedToText();
        /// <summary>
        /// [只读]bool to "已修改 未修改" 的字符串的转换器。
        /// </summary>
        public static Converter.ModifiedToText ModifiedToTextConverter { get { return modifiedToTextConverter; } }

        /// <summary>
        /// [静态构造方法]
        /// </summary>
        static PythonEditor()
        {
            Stream s = typeof(MainWindow).Assembly.GetManifestResourceStream("LunarSF.SHomeWorkshop.LunarMarkdownEditor.Python.xshd");
            if (s != null)
            {
                using (XmlReader reader = new XmlTextReader(s))
                {
                    pythonHighlighting = ICSharpCode.AvalonEdit.Highlighting.Xshd.
                        HighlightingLoader.Load(reader, HighlightingManager.Instance);
                }
            }
        }

        private PythonScriptListItem ownerItem;

        public PythonScriptListItem OwnerItem { get { return this.ownerItem; } }

        /// <summary>
        /// [构造方法]
        /// </summary>
        public PythonEditor(string fullPath, string titleText, PythonScriptListItem ownerItem)
        {
            InitializeComponent();

            this.fullPath = fullPath;
            this.ownerItem = ownerItem;
            if (ownerItem != null)
            {
                switch (ownerItem.Location)
                {
                    case PythonScriptLocation.Workspace:
                        tbLocation.Text = "【工作区脚本】";
                        break;
                    //case PythonScriptLocation.Global:
                    default:
                        tbLocation.Text = "【全局脚本】";
                        break;
                }
            }

            isLmePyScript = new FileInfo(fullPath).Name.StartsWith("Lme_");
            var preTitle = "";
            if (isLmePyScript)
            {
                btnOK.IsEnabled = false;
                btnSaveAndRun.IsEnabled = false;
                btnSaveAndClose.IsEnabled = false;
                preTitle = "[内置|只读]";

                miCut.IsEnabled = miCutMain.IsEnabled =
                    miUndo.IsEnabled = miUndoMain.IsEnabled =
                    miRedo.IsEnabled = miRedoMain.IsEnabled =
                    miPaste.IsEnabled = miPasteMain.IsEnabled =
                    miReplaceMain.IsEnabled = false;

                editorBase.IsReadOnly = true;
                tbModifiedinfo.Text = "内置脚本，不能修改！可复制到其它脚本文件中修改使用。";
                tbModifiedinfo.TextWrapping = TextWrapping.Wrap;
            }

            if (string.IsNullOrEmpty(titleText))
            {
                this.Title = Globals.AppName + preTitle + " - Python 脚本编辑器";
            }
            else this.Title = Globals.AppName + " - " + preTitle + titleText;

            editorBase.Options.ShowSpaces = false;
            editorBase.Options.ShowTabs = true;
            editorBase.Options.ConvertTabsToSpaces = false;
            editorBase.Options.AutoAlignTabs = false;
            editorBase.Options.HighlightCurrentLine = true;
            editorBase.Options.ShowEndOfLine = false;
            editorBase.ShowLineNumbers = true;
            editorBase.WordWrap = false;

            HighlightingManager.Instance.RegisterHighlighting("Python Highlighting", new string[] { ".py" }, pythonHighlighting);
            editorBase.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".py");

            //如果文件存在，载入之
            if (File.Exists(fullPath))
            {
                this.editorBase.Load(fullPath);
                this.editorBase.IsModified = false;
            }

            findAndReplaceDialog = new FindReplaceDialog(editorBase);
        }

        public PythonScriptListItem MasterItem { get; set; } = null;

        private bool isLmePyScript = false;

        private string fullPath = "";
        /// <summary>
        /// [只读]Python 脚本文件的磁盘路径。
        /// </summary>
        public string FullPath { get { return this.fullPath; } }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            SavePythonScriptFile();
        }

        private bool SavePythonScriptFile()
        {
            if (isLmePyScript)
            {
                LMessageBox.Show("此脚本是 LME 内置脚本，不能保存。" +
                    "请另外创建一个脚本文件，并将当前脚本复制到新创建的脚本文件中使用。\r\n\r\n" +
                    "★说明：不允许修改是因为这些内置脚本在安装 LME 的新版本后可能会更新——这会覆盖用户对脚本的修改成果。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            try
            {
                if (editorBase.IsModified == false) return true;

                using (StreamWriter sw = new StreamWriter(this.fullPath))
                {
                    sw.Write(this.editorBase.Text);
                    editorBase.IsModified = false;
                }

                //保存之后，要刷新对应列表项上的标题/描述/调用方式等三个选项。
                if (ownerItem != null)
                {
                    var oldGroupName = ownerItem.GroupName;
                    ownerItem.LastWriteTime = new FileInfo(this.fullPath).LastWriteTime;

                    string title = "Python 脚本";
                    string description = "<无描述文本>";
                    string callMode = "0";
                    string foregroundText = "Black";
                    string backgroundText = "Transparent";
                    string groupName = "";
                    string shortCutText = "";
                    string toolBarButtonText = "";
                    string popupButtonGroupsText = "";
                    Brush foreground, background;

                    int index = 1;
                    var line = editorBase.Document.GetLineByNumber(index);
                    while (line != null && index <= 80)
                    {
                        var lineText = editorBase.Document.GetText(line.Offset, line.Length);
                        Globals.MainWindow.TryReadPythonScriptTitle(lineText, ref title);
                        Globals.MainWindow.TryReadPythonScriptDescription(lineText, ref description);
                        Globals.MainWindow.TryReadPythonScriptCallMode(lineText, ref callMode);
                        Globals.MainWindow.TryReadPythonScriptItemForeground(lineText, ref foregroundText);
                        Globals.MainWindow.TryReadPythonScriptItemBackground(lineText, ref backgroundText);
                        Globals.MainWindow.TryReadPythonScriptItemGroupName(lineText, ref groupName);
                        Globals.MainWindow.TryReadPythonScriptShortCut(lineText, ref shortCutText);
                        Globals.MainWindow.TryReadPythonScriptToolBarButtonText(lineText, ref toolBarButtonText);
                        Globals.MainWindow.TryReadPythonScriptPopupButtonGroupsText(lineText, ref popupButtonGroupsText);

                        if (string.IsNullOrWhiteSpace(lineText) == false) index++;

                        line = line.NextLine;
                    }

                    if (string.IsNullOrWhiteSpace(title)) title = "未设置标题";
                    if (string.IsNullOrWhiteSpace(description)) description = "<无描述文本>";
                    if (string.IsNullOrWhiteSpace(callMode)) callMode = "0";

                    foreground = BrushManager.GetBrush(foregroundText);
                    if (foreground == null) foreground = BrushManager.GetBrushByChineseName(foregroundText);

                    background = BrushManager.GetBrush(backgroundText);
                    if (background == null) background = BrushManager.GetBrushByChineseName(backgroundText);

                    if (string.IsNullOrEmpty(title))
                    {
                        this.Title = Globals.AppName + " - Python 脚本编辑器";
                    }
                    else this.Title = Globals.AppName + " - " + title;

                    ownerItem.Title = title;
                    ownerItem.TbDescription.Text = description;
                    ownerItem.HeaderForeground = foreground;
                    ownerItem.HeaderBackground = background;
                    ownerItem.GroupName = groupName;
                    ownerItem.RefreshGroupName();
                    ownerItem.RefreshCallMode(ownerItem.ConvertToPythonScriptCallMode(callMode));
                    ownerItem.ToolBarButtonText = toolBarButtonText;
                    ownerItem.PopupButtonGroupsText = popupButtonGroupsText;

                    ownerItem.ShortCutText = shortCutText;
                    ownerItem.RefreshShortCut();

                    if (string.IsNullOrWhiteSpace(toolBarButtonText) == false)
                    {
                        Button btn = null;
                        PythonScriptMenuItem mi = null;
                        switch (OwnerItem.Location)
                        {
                            case PythonScriptLocation.Workspace:
                                {
                                    foreach (var ue in Globals.MainWindow.workspacePyScriptsToolBar.Items)
                                    {
                                        var tbtn = ue as Button;
                                        if (tbtn == null || tbtn.Tag == null) continue;
                                        var psli = tbtn.Tag as PythonScriptListItem;
                                        if (psli == null || psli != ownerItem) continue;

                                        btn = tbtn;
                                    }
                                    foreach (var ue in Globals.MainWindow.cmWorkspacePythonScripts.Items)
                                    {
                                        var cmi = ue as PythonScriptMenuItem;
                                        if (cmi == null || cmi.Tag == null) continue;
                                        var psli = cmi.Tag as PythonScriptListItem;
                                        if (psli == null || psli != ownerItem) continue;

                                        mi = cmi;
                                    }
                                    break;
                                }
                            default:
                                {
                                    foreach (var ue in Globals.MainWindow.pyScriptsToolBar.Items)
                                    {
                                        var tbtn = ue as Button;
                                        if (tbtn == null || tbtn.Tag == null) continue;
                                        var psli = tbtn.Tag as PythonScriptListItem;
                                        if (psli == null || psli != ownerItem) continue;

                                        btn = tbtn;
                                    }
                                    foreach (var ue in Globals.MainWindow.cmGlobalsPythonScripts.Items)
                                    {
                                        var cmi = ue as PythonScriptMenuItem;
                                        if (cmi == null || cmi.Tag == null) continue;
                                        var psli = cmi.Tag as PythonScriptListItem;
                                        if (psli == null || psli != ownerItem) continue;

                                        mi = cmi;
                                    }
                                    break;
                                }
                        }

                        if (btn == null)
                        {
                            btn = new Button()
                            {
                                FontSize = 14,
                                Content = ownerItem.ToolBarButtonText,
                                Style = TryFindResource("LSquareButtonStyle") as Style,
                                BorderThickness = new Thickness(1, 1, 1, 1),
                                Margin = new Thickness(2, 2, 2, 0),
                                Height = 20,
                                Padding = new Thickness(4, 0, 4, 0),
                                FontWeight = FontWeights.Normal,
                                Tag = ownerItem,
                            };

                            if (string.IsNullOrWhiteSpace(OwnerItem.ShortCutText))
                            {
                                btn.ToolTip = ownerItem.Title;
                            }
                            else
                            {
                                btn.ToolTip = "【" + ownerItem.Title + "】";
                            }

                            var btnContextMenu = new ContextMenu();
                            var miOpenScript = new MenuItem()
                            {
                                Header = $"编辑 {ownerItem.Title}(_E)",
                                Style = TryFindResource("MetroMenuItem") as Style,
                                Tag = ownerItem,
                            };
                            miOpenScript.Click += MiOpenScript_Click;
                            btnContextMenu.Items.Add(miOpenScript);
                            btn.ContextMenu = btnContextMenu;
                            btn.MouseRightButtonDown += Btn_MouseRightButtonDown;

                            if (string.IsNullOrWhiteSpace(ownerItem.ShortCutText) == false && ownerItem.ShortCutText != "无")
                            {
                                btn.ToolTip = ownerItem.Title + "\r\n" + ownerItem.ShortCutText;
                            }
                            else
                            {
                                btn.ToolTip = ownerItem.Title;
                            }

                            btn.Click += Btn_Click;

                            switch (OwnerItem.Location)
                            {
                                case PythonScriptLocation.Workspace:
                                    {
                                        Globals.MainWindow.workspacePyScriptsToolBar.Items.Add(btn);
                                        Globals.MainWindow.cmWorkspacePythonScripts.Items.Add(new PythonScriptMenuItem(btn));
                                        if (Globals.MainWindow.workspacePyScriptsToolBar.Items.Count > 0)
                                        {
                                            Globals.MainWindow.workspacePyScriptsToolBar.Visibility = Visibility.Visible;
                                            Globals.MainWindow.cmWorkspacePythonScripts.Visibility =
                                                Globals.MainWindow.mWorkspacePythonScripts.Visibility = Visibility.Visible;
                                        }
                                        else
                                        {
                                            Globals.MainWindow.workspacePyScriptsToolBar.Visibility = Visibility.Collapsed;
                                            Globals.MainWindow.cmWorkspacePythonScripts.Visibility =
                                                Globals.MainWindow.mWorkspacePythonScripts.Visibility = Visibility.Collapsed; ;
                                        }
                                        break;
                                    }
                                // case PythonScriptLocation.Global:
                                default:
                                    {
                                        Globals.MainWindow.pyScriptsToolBar.Items.Add(btn);
                                        if (Globals.MainWindow.pyScriptsToolBar.Items.Count > 0)
                                        {
                                            Globals.MainWindow.pyScriptsToolBar.Visibility = Visibility.Visible;
                                            Globals.MainWindow.cmGlobalsPythonScripts.Visibility =
                                                Globals.MainWindow.mGlobalPythonScripts.Visibility = Visibility.Visible;
                                        }
                                        else
                                        {
                                            Globals.MainWindow.pyScriptsToolBar.Visibility = Visibility.Collapsed;
                                            Globals.MainWindow.cmGlobalsPythonScripts.Visibility =
                                                Globals.MainWindow.mGlobalPythonScripts.Visibility = Visibility.Collapsed;
                                        }
                                        break;
                                    }
                            }

                            if (Globals.MainWindow.PerspectiveMode == Perspective.MiniMode)
                            {
                                if (Globals.MainWindow.workspacePyScriptsToolBar.Items.Count <= 0 &&
                                    Globals.MainWindow.pyScriptsToolBar.Items.Count <= 0)
                                {
                                    Globals.MainWindow.mainToolBarTray.Visibility = Visibility.Collapsed;
                                    Globals.MainWindow.rdTopToolbarArea.Height = new GridLength(0);
                                }
                                else
                                {
                                    Globals.MainWindow.rdTopToolbarArea.Height = new GridLength(0, GridUnitType.Auto);
                                    Globals.MainWindow.mainToolBarTray.Visibility = Visibility.Visible;
                                }
                            }
                            else
                            {
                                Globals.MainWindow.mainToolBarTray.Visibility = Visibility.Visible;
                            }
                        }
                        else
                        {
                            //if (string.IsNullOrWhiteSpace(ownerItem.ToolBarButtonText)) { }   // 肯定不是，前面已经判断过了
                            //else
                            //{
                            mi.Header =  // btn 非 null，则 mi 必非 null！
                                btn.Content = ownerItem.ToolBarButtonText;

                            if (string.IsNullOrWhiteSpace(ownerItem.ShortCutText) == false && ownerItem.ShortCutText != "无")
                            {
                                btn.ToolTip = $"【{ownerItem.ShortCutText.ToUpper()}】{ownerItem.Title}";
                            }
                            else
                            {
                                btn.ToolTip = ownerItem.Title;
                            }
                            //}
                        }
                    }
                    else
                    {
                        switch (ownerItem.Location)
                        {
                            case PythonScriptLocation.Workspace:
                                {
                                    Button btn = null;
                                    foreach (var ue in Globals.MainWindow.workspacePyScriptsToolBar.Items)
                                    {
                                        var tbtn = ue as Button;
                                        if (tbtn == null || tbtn.Tag == null) continue;
                                        var psli = tbtn.Tag as PythonScriptListItem;
                                        if (psli == null || psli != ownerItem) continue;

                                        btn = tbtn;
                                        break;
                                    }

                                    if (btn != null)
                                    {
                                        Globals.MainWindow.workspacePyScriptsToolBar.Items.Remove(btn);
                                        if (Globals.MainWindow.workspacePyScriptsToolBar.Items.Count <= 0)
                                        {
                                            Globals.MainWindow.workspacePyScriptsToolBar.Visibility = Visibility.Collapsed;
                                        }
                                    }
                                    break;
                                }
                            //case PythonScriptLocation.Global:
                            default:
                                {
                                    Button btn = null;
                                    foreach (var ue in Globals.MainWindow.pyScriptsToolBar.Items)
                                    {
                                        var tbtn = ue as Button;
                                        if (tbtn == null || tbtn.Tag == null) continue;
                                        var psli = tbtn.Tag as PythonScriptListItem;
                                        if (psli == null || psli != ownerItem) continue;

                                        btn = tbtn;
                                        break;
                                    }

                                    if (btn != null)
                                    {
                                        Globals.MainWindow.pyScriptsToolBar.Items.Remove(btn);
                                        if (Globals.MainWindow.pyScriptsToolBar.Items.Count <= 0)
                                        {
                                            Globals.MainWindow.pyScriptsToolBar.Visibility = Visibility.Collapsed;
                                        }
                                    }
                                    break;
                                }
                        }
                    }

                    if (oldGroupName != groupName)
                    {
                        var result = LMessageBox.Show("您为当前脚本设置了新的分组名称，需要立即更新脚本在列表中的位置吗？\r\n\r\n　　如果选择【否】，将在下一次启动时自动更新。", Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Question);
                        if (result == MessageBoxResult.Yes)
                        {
                            Globals.MainWindow.LoadPythonScriptFiles();
                        }
                    }

                    foreach (var ue in Globals.MainWindow.mainTabControl.Items)
                    {
                        var edit = ue as MarkdownEditor;
                        if (edit == null || edit.EditorBase.PopupToolBar == null) continue;

                        edit.EditorBase.PopupToolBar.LoadPythonScriptButtonGroups();
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                LMessageBox.Show(ex.Message, Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }
        }

        private void Btn_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            var btn = sender as Button;
            if (btn == null || btn.ContextMenu == null) return;

            btn.ContextMenu.IsOpen = true;
        }

        private void MiOpenScript_Click(object sender, RoutedEventArgs e)
        {
            var mi = sender as MenuItem;
            if (mi == null) return;

            var ownerItem = mi.Tag as PythonScriptListItem;
            if (ownerItem == null) return;

            ownerItem.EditScriptFile();
        }

        private void Btn_Click(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            if (btn == null) return;

            var psli = btn.Tag as PythonScriptListItem;
            if (psli == null) return;

            psli.RunScript();
        }

        private FindReplaceDialog findAndReplaceDialog;

        private void btnSaveAndRun_Click(object sender, RoutedEventArgs e)
        {
            if (SavePythonScriptFile())
            {
                if (OwnerItem != null)
                {
                    var startTime = DateTime.Now;
                    var startTag = $"\r\n[Start From:{startTime.ToShortDateString()} {startTime.ToShortTimeString()}]==========\r\n";
                    var result = PythonScriptListItem.RunScript(OwnerItem.CallMode, OwnerItem.FullPath, false);
                    var endTime = DateTime.Now;
                    var endTag = $"\r\n[End At:{endTime.ToShortDateString()} {endTime.ToShortTimeString()}]----------\r\n";
                    if (result != null)
                    {
                        tbxOutput.AppendText(startTag);
                        tbxOutput.AppendText(result.OutputInfo);
                        tbxOutput.AppendText(endTag);
                        tbxOutput.ScrollToEnd();

                        if (result.ErrInfo.Length > 0)
                        {
                            tbxErr.AppendText(startTag);
                            tbxErr.AppendText(result.ErrInfo);
                            tbxErr.AppendText(endTag);
                            tbxErr.ScrollToEnd();
                        }
                    }
                }
            }
        }

        private void btnSaveAndClose_Click(object sender, RoutedEventArgs e)
        {
            if (SavePythonScriptFile()) this.Close();
        }

        private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (isLmePyScript) return;

            if (editorBase.IsModified)
            {
                var answer = LMessageBox.Show("编辑区的脚本已修改，要保存吗？", Globals.AppName,
                    MessageBoxButton.YesNoCancel, MessageBoxImage.Warning, "", null, this);
                switch (answer)
                {
                    case MessageBoxResult.Yes:
                        {
                            SavePythonScriptFile();
                            break;
                        }
                    case MessageBoxResult.No:
                        {
                            break;
                        }
                    case MessageBoxResult.Cancel:
                        {
                            e.Cancel = true;
                            break;
                        }
                }
            }
        }

        private void miCut_Click(object sender, RoutedEventArgs e)
        {
            editorBase.Cut();
        }

        private void miCopy_Click(object sender, RoutedEventArgs e)
        {
            editorBase.Copy();
        }

        private void miPaste_Click(object sender, RoutedEventArgs e)
        {
            editorBase.Paste();
        }

        private void miUndo_Click(object sender, RoutedEventArgs e)
        {
            if (editorBase.CanUndo) editorBase.Undo();
        }

        private void miRedo_Click(object sender, RoutedEventArgs e)
        {
            if (editorBase.CanRedo) editorBase.Redo();
        }

        private void miSelectAll_Click(object sender, RoutedEventArgs e)
        {
            editorBase.SelectAll();
        }

        private void MetroWindow_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            // 这几个快捷键都是全窗口级别的。
            KeyStates ksRShift = Keyboard.GetKeyStates(Key.RightShift);
            KeyStates ksLShift = Keyboard.GetKeyStates(Key.LeftShift);
            KeyStates ksLAlt = Keyboard.GetKeyStates(Key.LeftAlt);
            KeyStates ksRAlt = Keyboard.GetKeyStates(Key.RightAlt);
            KeyStates ksLCtrl = Keyboard.GetKeyStates(Key.LeftCtrl);
            KeyStates ksRCtrl = Keyboard.GetKeyStates(Key.RightCtrl);

            bool isCtrl, isShift, isAlt;

            isShift = (ksLShift & KeyStates.Down) > 0 || (ksRShift & KeyStates.Down) > 0;
            isCtrl = (ksLCtrl & KeyStates.Down) > 0 || (ksRCtrl & KeyStates.Down) > 0;
            isAlt = (ksLAlt & KeyStates.Down) > 0 || (ksRAlt & KeyStates.Down) > 0;

            switch (e.Key)
            {
                case Key.S:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            SavePythonScriptFile();
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.F5:
                    {
                        //保存并执行
                        if (!isCtrl && !isShift && !isAlt)
                        {
                            if (SavePythonScriptFile())
                            {
                                if (this.OwnerItem != null)
                                {
                                    PythonScriptListItem.RunScript(this.OwnerItem.CallMode, this.OwnerItem.FullPath);
                                    e.Handled = true;
                                }
                            }
                        }
                        break;
                    }
                case Key.F6:
                    {
                        if (isCtrl && isShift && !isAlt)
                        {
                            if (SavePythonScriptFile())
                            {
                                this.Close();
                                e.Handled = true;
                            }
                        }
                        break;
                    }
                case Key.H:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            Replace();
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.F:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            Find();
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D0:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            miShowCodeArea_Click(sender, e);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D1:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            miShowOutputInfo_Click(sender, e);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D2:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            miResetLayout_Click(sender, e);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.D3:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            miShowErrorInfo_Click(sender, e);
                            e.Handled = true;
                        }
                        break;
                    }
                case Key.R:
                    {
                        if (isCtrl && !isShift && !isAlt)
                        {
                            miAutoWrap_Click(sender, e);
                            e.Handled = true;
                        }
                        break;
                    }
            }
        }

        private void Replace()
        {
            findAndReplaceDialog.Owner = this;
            findAndReplaceDialog.tabMain.SelectedIndex = 1;
            findAndReplaceDialog.Show();
            findAndReplaceDialog.Activate();

            if (editorBase.IsReadOnly)
            {
                findAndReplaceDialog.IsReplacePanelVisible = false;

                if (!editorBase.TextArea.Selection.IsMultiline)
                {
                    findAndReplaceDialog.txtFind.Text = findAndReplaceDialog.txtFind2.Text = editorBase.TextArea.Selection.GetText();
                    findAndReplaceDialog.txtFind.SelectAll();
                    findAndReplaceDialog.txtFind.SelectAll();
                    findAndReplaceDialog.txtFind.Focus();
                }
            }
            else
            {
                findAndReplaceDialog.IsReplacePanelVisible = true;

                if (!editorBase.TextArea.Selection.IsMultiline)
                {
                    findAndReplaceDialog.txtFind.Text = findAndReplaceDialog.txtFind2.Text = editorBase.TextArea.Selection.GetText();
                    findAndReplaceDialog.txtFind.SelectAll();
                    findAndReplaceDialog.txtFind2.SelectAll();
                    findAndReplaceDialog.txtFind2.Focus();
                }
            }

        }

        private void Find()
        {
            findAndReplaceDialog.Owner = this;
            findAndReplaceDialog.tabMain.SelectedIndex = 0;
            findAndReplaceDialog.Show();
            findAndReplaceDialog.Activate();

            if (!editorBase.TextArea.Selection.IsMultiline)
            {
                findAndReplaceDialog.txtFind.Text = findAndReplaceDialog.txtFind2.Text = editorBase.TextArea.Selection.GetText();
                findAndReplaceDialog.txtFind.SelectAll();
                findAndReplaceDialog.txtFind.SelectAll();
                findAndReplaceDialog.txtFind.Focus();
            }

            if (editorBase.IsReadOnly)
            {
                findAndReplaceDialog.IsReplacePanelVisible = false;
            }
            else findAndReplaceDialog.IsReplacePanelVisible = true;
        }

        private void miFindMain_Click(object sender, RoutedEventArgs e)
        {
            Find();
        }

        private void miReplaceMain_Click(object sender, RoutedEventArgs e)
        {
            Replace();
        }

        private void miAutoWrap_Click(object sender, RoutedEventArgs e)
        {
            bool wrap =
                editorBase.WordWrap = (miAutoWrap.IsChecked = !miAutoWrap.IsChecked);

            if (wrap)
            {
                tbxOutput.TextWrapping = TextWrapping.Wrap;
                tbxErr.TextWrapping = TextWrapping.Wrap;
            }
            else
            {
                tbxOutput.TextWrapping = TextWrapping.NoWrap;
                tbxErr.TextWrapping = TextWrapping.NoWrap;
            }
        }

        private void btnTopmost_Click(object sender, RoutedEventArgs e)
        {
            this.Topmost = !this.Topmost;
            if (this.Topmost)
            {
                backgroundGridTopMost.Background = Brushes.DarkCyan;
            }
            else
            {
                backgroundGridTopMost.Background = Brushes.Transparent;
            }
        }

        private void miShowOutputInfo_Click(object sender, RoutedEventArgs e)
        {
            rdOutputArea.Height = new GridLength(3, GridUnitType.Star);
            rdMainEditArea.Height = new GridLength(1, GridUnitType.Star);
            cdLeft.Width = new GridLength(4, GridUnitType.Star);
            cdRight.Width = new GridLength(1, GridUnitType.Star);
        }

        private void miShowErrorInfo_Click(object sender, RoutedEventArgs e)
        {
            rdOutputArea.Height = new GridLength(3, GridUnitType.Star);
            rdMainEditArea.Height = new GridLength(1, GridUnitType.Star);
            cdLeft.Width = new GridLength(1, GridUnitType.Star);
            cdRight.Width = new GridLength(4, GridUnitType.Star);
        }

        private void miResetLayout_Click(object sender, RoutedEventArgs e)
        {
            rdMainEditArea.Height = new GridLength(3, GridUnitType.Star);
            rdOutputArea.Height = new GridLength(1, GridUnitType.Star);
            cdLeft.Width = new GridLength(1, GridUnitType.Star);
            cdRight.Width = new GridLength(1, GridUnitType.Star);
        }

        private void miShowCodeArea_Click(object sender, RoutedEventArgs e)
        {
            rdMainEditArea.Height = new GridLength(1, GridUnitType.Star);
            rdOutputArea.Height = new GridLength(0, GridUnitType.Star);
        }

        private void MetroWindow_Closed(object sender, EventArgs e)
        {
            if (this.MasterItem != null)
                MasterItem.Editor = null;
        }

        /// <summary>
        /// 解决 Win10 下菜单位置偏移的问题。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Menu_Initialized(object sender, EventArgs e)
        {
            var m = sender as MenuItem;
            if (m == null) return;
            var cm = m.ContextMenu;
            if (cm == null) return;

            cm.Placement = PlacementMode.Bottom;
            cm.PlacementTarget = m;
            m.ContextMenu = null;
            m.Tag = cm;

            cm.Opened += Cm_Opened;
            cm.Closed += Cm_Closed;
            m.PreviewMouseLeftButtonDown += M_PreviewMouseLeftButtonDown;
        }

        private void M_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var m = sender as MenuItem;
            if (m == null) return;
            var cm = m.Tag as ContextMenu;
            if (cm == null) return;

            cm.IsOpen = true;
        }

        private void Cm_Closed(object sender, RoutedEventArgs e)
        {
            var cm = sender as ContextMenu;
            if (cm == null || cm.PlacementTarget == null) return;
            var m = cm.PlacementTarget as MenuItem;
            if (m == null) return;

            m.Background = Brushes.Transparent;
            m.Foreground = Brushes.White;
        }

        private void Cm_Opened(object sender, RoutedEventArgs e)
        {
            var cm = sender as ContextMenu;
            if (cm == null || cm.PlacementTarget == null) return;
            var m = cm.PlacementTarget as MenuItem;
            if (m == null) return;

            m.Background = Brushes.LightGray;
            m.Foreground = Brushes.Black;

            var point = cm.PlacementTarget.PointToScreen(new Point(0, 0));
            //if (Environment.OSVersion.Version.Major > 6 ||
            //    (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1))  // win 8 以上（6.2）
            //{
            cm.HorizontalOffset = 0;  // -cm.ActualWidth + m.ActualWidth + 6;// point.X - splitMenu2.ActualWidth + btnFindHeaders_AppendArrow.ActualWidth;
            cm.VerticalOffset = 0;  // point.Y - 8;
            //}
        }

        private void Menu_Click(object sender, RoutedEventArgs e)
        {
            var menu = sender as MenuItem;
            if (menu == null || menu.Tag == null) return;
            var cm = menu.Tag as ContextMenu;
            if (cm == null) return;

            cm.IsOpen = true;
        }
    }
}
